package com.hobee.basic.config.datasource;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author junjie.li
 * @date 2020/6/29 18:03
 */
@Configuration
public class DataSourceConfig {

    private static Logger LOGGER = LoggerFactory.getLogger(DataSourceConfig.class);

    /**
     * 配置写库数据源
     *
     * @return javax.sql.DataSource
     */
    @Bean(name = "DbMaster")
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    public DataSource dataSourceMaster() {
        LOGGER.info("master 写数据源加载");
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 配置读库数据源
     *
     * @return javax.sql.DataSource
     */
    @Bean(name = "DbSlave")
    @ConfigurationProperties(prefix = "spring.datasource.druid.slave")
    public DataSource dataSourceSlave() {
        LOGGER.info("slave 读数据源加载");
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 动态获取数据源
     *
     * @param master 写
     * @param slave  读
     * @return javax.sql.DataSource
     */
    @Primary
    @Bean(name = "dataSourceRouter")
    public DataSource dataSourceRouter(@Qualifier("DbMaster") DataSource master, @Qualifier("DbSlave") DataSource slave) {
        DataSourceRouter dataSourceRouter = new DataSourceRouter();
        // 配置多数据源
        Map<Object, Object> map = new HashMap<>(5);
        // key需要跟ThreadLocal中的值对应
        map.put(DataSourceEnum.MASTER.getCodeName(), master);
        map.put(DataSourceEnum.SLAVE.getCodeName(), slave);
        dataSourceRouter.setDefaultTargetDataSource(master);
        dataSourceRouter.setTargetDataSources(map);
        return dataSourceRouter;
    }

    /**
     * 注入动态数据源 DataSourceTransactionManager 用于事务管理(事务回滚只针对同一个数据源)
     *
     * @param dataSource 从路由中获取到的数据源
     * @return org.springframework.jdbc.datasource.DataSourceTransactionManager
     */
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(@Qualifier("dataSourceRouter") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}
